package org.reference.generic.work;

import java.util.ArrayList;
import java.util.List;

import org.reference.generic.base.Item;
import org.reference.generic.base.Manager;
import org.reference.generic.base.Parameter;
import org.reference.generic.base.ReferenceParameter;
import org.reference.generic.work.Machine.OnCompleteListenner;

import util.Log;
/**
 * 
 */
public class MachineManager extends Manager implements Machine.OnCompleteListenner {

    /**
     * 
     */
    public MachineManager() {
    	setName("MACHINE_MANAGER");
    }
    
    private long breakTime;
    private long currentTime;
    private double cmax;
    private Schedule schedule;
    private int index;
    private List<Machine> machineIndex = new ArrayList<Machine>(); // machine 생성 갯수를 관리 
    
   
    private OnCompleteListenner onCompleteListenner;
    /**
     * @param onCompleteListenner
     */
    public void setOnCompleteListenner(OnCompleteListenner onCompleteListenner) {
        this.onCompleteListenner = onCompleteListenner;
    }

    /**
     * @param schedule
     */
    public void run(Schedule schedule) {
    	this.schedule = schedule;
    	
    while(schedule.getJobList().size()>0){
    	//종료조건, 모든 잡이 전부 실행 될 때까
    	if (schedule.isAvailable()){
    		for(int i=0; i<machineIndex.size();i++){
    			// 시간이 0일때 모든 머신에 잡을 할당 할 수 있기 때문에 먼저 할당을 하고 시작함 
    			if(machineIndex.get(index).getReadyTime()<=currentTime){
    				machineIndex.get(i).run(schedule.getNextJob());
    				Log.debug("선택된 머신 ppppppp " +machineIndex.get(i).getIndex());
    				}
    			}
    	}else{
    		//스케줄이 실행되지 않아도 현재시간 카운트 => 모든 머신들이 작업을 하고 있을 경우에는 잡 리스트에 잡이 있어도 실행 할 수가 없기 때문에 현재 시간만 카운트  
    		checkMachineFree(currentTime);
    		currentTime++;
    		breakTime++;
    		System.out.println("2123123"+currentTime);
    	}
    	    	
    }
  }
    	
    /**
     * @return
     */
    public double getCMAX() {
    	double result_cmax = cmax;
        //return (double)(result_cmax / 1000*60);
        return (double)(result_cmax);
    }
    
    public Machine getMachine(){
    	
    	for(Item m : itemList){
    		if(!((Machine)m).isBusy())
    			return (Machine) m;
    	}
    	return null;
    }
    

	@Override
	public void init(Parameter parameters, List<ReferenceParameter> rpList ) {
		
		for(int i=0 ; i<rpList.get(index).getMachineNumber(); i++){
			Machine machine = new Machine();
			machine.setIndex(i);
			machine.setOnCompleteListenner(this); 
			itemList.add(machine);
			machineIndex.add(machine);
		}
		
//		if(param.getName().equalsIgnoreCase(Parameter.TYPE_MACHINE_STEP)) {
//			Machine machine = new Machine();
//			machine.setStep(param.getValueToInt());
//			machine.setOnCompleteListenner(this);   //癒몄떊 oncomleteListenner�뿉 machine manager瑜� �꽔�쓬.
//			itemList.add(machine);
//		}
//	}
	}
	
	@Override
	public void getResult() {
		
		//System.out.println("Machine Cmax value " + getCMAX());
	
		getMachineIndex();
		//return null;
	}

	@Override
	public void onComplete(Machine machine) {
		
		Job job = schedule.getNextJob();
		
		if (job != null) {
			machine.run(job);
		} else {
			for (Item item : itemList) {				
				if (((Machine) item).isBusy()) {
					cmax = 0;
					return;
				}   
				
			}
	
			//onComplete();
			
			cmax = machine.getTotalWorkingTime();
			
			if (onCompleteListenner == null) return;
	    	onCompleteListenner.onComplete(this);  // 머신 매니저의 onComplete 호출 	
			
	    	getResult();
		}
	}

	public int getIndex() {
		return index;
	}

	public void setIndex(int index) {
		this.index = index;
	}

	public interface OnCompleteListenner {
        /**
         * @param machine
         */
        public abstract void onComplete(MachineManager machineManger);

    }

	public List<Machine> getMachineIndex() {
		return machineIndex;
	}

	public long getCurrentTime() {
		return currentTime;
	}
	
	
	public void checkMachineFree(long currentTime){
		for(int j=0; j<machineIndex.size(); j++){
			if(currentTime==machineIndex.get(j).getReadyTime()){
				//현재시간과 머신레디타임이 같을 경우에 머신 종료 
				machineIndex.get(j).onComplete();
			}
		}
	}
}